package com.cskaoyan.javse.oop2._1extends._8hidden;

/**
 * 继承中属性的隐藏
 * 在上面章节中，我们已经知道，父子类的成员是允许同名的。那么如果父子类属性同名了，那么不使用super区分，直接访问的效果是什么样的呢？
 *
 * 现在我们直接创建子类对象，使用子类引用接收。会发现访问的结果是子类中属性的取值，那么父类中的那个成员变量去哪了呢？首先它肯定是存在的，这一点随便写一个父类成员变量的Getter方法就可以验证了。这说明使用"对象名点"访问成员变量 这个语法，可能存在一些特殊的机制，接下来我们就来探讨这种机制。
 *
 * 接下来探讨"对象名点成员变量"的访问机制,主要从两个角度:
 *      1.访问范围
 *      2.访问结果
 * 对象名就是一个引用,当存在继承时,有父类,有子类,这个引用可以有三种创建形式:
 *      1.子类对象用子类引用接收
 *      2.父类对象用父类对象接收
 *      3.子类对象用父类引用接收
 *
 * 先探讨它们的访问范围：
 *      1.子类对象用子类引用接收
 *          发现可以访问子类自己的，还有直接父类的，也包括间接父类的（Object）
 *
 *      2.父类对象用父类对象接收
 *          发现可以访问父类的（Object），可以访问自己的，但是不能访问子类的。
 *
 *      3.子类对象用父类引用接收
 *          发现可以访问父类的（Object），可以访问自己的，但是不能访问子类的。
 *
 * 以上得出结论：
 *      首先，对象名点成员变量，它的访问范围是一个编译上的概念，能访问就能通过编译，不能访问就会编译报错。
 *      我们会发现使用对象名点访问成员变量，编译器有以下检索机制：
 *      声明是一个告诉编译器数据类型的过程，所以对于一个变量，编译器只能通过声明中的数据类型知道你是何种类型。编译器在决定是否通过编译时，只能看到引用的类型，它不知道对象的类型。
 *      先从引用的自身类中去找，如果能够直接找到该成员变量，不会编译报错。
 *      如果找不到就去父类中找，直到找到Object，如果还没找到，就会编译报错。
 *
 *    也就是说，对象名点成员变量的访问范围，只需要根据引用的数据类型就可以确定了。
 *
 *    在Java当中，一个子类是可以明确知道它有几个父类，但是父类知道自己有子类吗？知道自己有几个子类吗？
 *    不知道
 *
 * -------
 *  再探讨它们的访问结果：
 *      1.子类对象用子类引用接收
 *      2.父类对象用父类对象接收
 *      3.子类对象用父类引用接收
 * 通过测试，它的访问结果仍然根据引用的类型来决定
 *
 * 综上，对象名点成员变量的访问范围和访问结果都是根据引用的数据类型来决定的。完全不需要关心引用指向什么对象。
 *
 * > 注意事项：
 * > 1. 父子类中的同名成员变量它们各自有存储的区域，父类的同名成员变量被子类同名成员变量隐藏了，称之为"属性的隐藏"。
 * >    但我们仍然可以通过父类中的Getter方法，或者通过super去访问到父类中同名成员变量，当然它们都受访问权限限制。
 * > 2. 静态成员变量在父子类中也存在同名的情况，但是它们不是覆盖也不是隐藏，而是互相独立的两个静态成员变量。
 *
 *
 *
 *
 * @since 11:12
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 用三种方式创建对象
        Son s = new Son();
        System.out.println(s.sonVar); // 200
        System.out.println(s.var); // 100

        Father f = new Father();
        System.out.println(f.fatherVar); // 20
        System.out.println(f.var); // 10

        Father fs = new Son();
        System.out.println(fs.fatherVar);
        System.out.println(fs.var);
    }
}

class Father {
    int var = 10;
    int fatherVar = 20;

}

class Son extends Father {
    int var = 100;
    int sonVar = 200;
}